import { LingxinApiClientBase } from './LingxinApiClientBase.js'

/**
 * 文本输入语音输出客户端
 */
export class LingxinApiClientT2v extends LingxinApiClientBase {
  // 灵芯应用的唯一标识
  lingxinAppCode = 'app_t_cbe0f145-2d6c-4181-a2ce-af1c262bafc8'
  // 任务ID
  taskId = ''

  // Promise 回调函数
  resolveCallback
  rejectCallback

  // 语音数据
  audioData = null
  // 音频数据合并
  arrayBufferMerger

  constructor(lingxinAppId, appId, appLicenseKey) {
    super(lingxinAppId, appId, appLicenseKey)
    this.taskId = `${this.appId}^1^1`
    this.arrayBufferMerger = new SimpleArrayBufferMerger()
  }

  /**
   * 文本转语音
   * @param {String} text
   */
  textToVoice(text) {
    return new Promise((resolve, reject) => {
      if (!this.isConnected) {
        // 需要先初始化
        this.setupSocket()
          .then(result => {
            console.log('socket链接成功')
            this.doMessageInteraction(resolve, reject, text)
          })
          .catch(error => {
            console.log('socket链接错误：', error)
            reject(error)
          })
      } else {
        this.doMessageInteraction(resolve, reject, text)
      }
    })
  }

  doMessageInteraction(resolve, reject, text) {
    this.resolveCallback = resolve
    this.rejectCallback = reject

    // 发送start_task指令
    this.send(
      JSON.stringify({
        header: {
          action: 'start_task',
          task_id: this.taskId
        },
        payload: {
          agent_basic_inputs: {
            user_input: text
          },
          agent_code: this.lingxinAppCode,
          input_mode: 'no_voice'
        }
      })
    )
      .then(result => {
        console.log('发送start_task命令成功')
      })
      .catch(error => {
        console.log('发送start_task命令失败')
        this.rejectCallback(error)
      })
  }

  /**
   * 接收到云端的推送信息
   * @param {String | ArrayBuffer} message
   */
  onMessageRecived(message) {
    if (typeof message === 'string') {
      // 命令
      console.log('接收命令消息：', message)
      let data
      try {
        data = JSON.parse(message)
      } catch (error) {
        console.error('解析JSON消息失败:', error)
        this.rejectCallback('解析JSON消息失败')
        return
      }

      switch (data.header?.action) {
        case 'task_started':
          console.log('云端已初始化完成')
          break
        case 'task_terminated':
          console.log('任务已经中断')
          break
        case 'audio_response_start':
          console.log('准备接受语音数据')
          break
        case 'audio_response_end':
          console.log('完成接受语音数据,准备发送任务结束指令')
          this.send(
            JSON.stringify({
              header: {
                action: 'end_task',
                task_id: this.taskId
              },
              payload: {}
            })
          )
            .then(result => {
              console.log('发送end_task命令成功')
            })
            .catch(error => {
              console.log('发送end_task命令失败')
              this.rejectCallback(error)
            })
          break
        case 'task_ended':
          console.log('任务已经结束')
          this.audioData = this.arrayBufferMerger.getArrayBuffer()
          this.resolveCallback(this.audioData)
          break
        default:
          break
      }
    } else if (message instanceof ArrayBuffer) {
      // 音频数据
      console.log('接收音频数据：', message)
      this.arrayBufferMerger.addChunk(message)
    } else {
      // 未知类型
      console.log('接收到消息：', message)
    }
  }
}

export class SimpleArrayBufferMerger {
  constructor() {
    this.data = new Uint8Array(0)
  }

  addChunk(buffer) {
    const newChunk = new Uint8Array(buffer)
    const newData = new Uint8Array(this.data.length + newChunk.length)
    newData.set(this.data, 0)
    newData.set(newChunk, this.data.length)
    this.data = newData
    return this.data.buffer // 直接返回 ArrayBuffer
  }

  getArrayBuffer() {
    return this.data.buffer
  }
}
